Add @e2b/id: prefixed IDs for E2B resources - #1627
Conversation
|
PR SummaryLow Risk Overview
Reviewed by Cursor Bugbot for commit 27a952b. Bugbot is set up for automated code reviews on this repo. Configure here. |
Package ArtifactsBuilt from 8df97be. Download artifacts from this workflow run. JS SDK ( npm install ./e2b-2.36.2-prefixed-id-packages.0.tgzCLI ( npm install ./e2b-cli-2.16.1-prefixed-id-packages.0.tgzPython SDK ( pip install ./e2b-2.35.0+prefixed.id.packages-py3-none-any.whl |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit ebc5708. Configure here.
| 'prefix', | ||
| `"${id}" is a ${named} ID, not a ${kind} ID.`, | ||
| named | ||
| ) |
There was a problem hiding this comment.
Wrong kind lookup without separator
Medium Severity
When decodeId rejects an ID with no underscore, id.indexOf(SEPARATOR) is -1, so id.slice(0, -1) drops the last character before the prefix lookup. That can set actualKind and the error message from a truncated string, and disagrees with Python's split behavior on the same input.
Reviewed by Cursor Bugbot for commit ebc5708. Configure here.
A three-character kind prefix, an underscore, and the 26-character rotated
base32 encoding of a UUID:
prj_uk75vf2v7iagp2kgn7pfze3car
sbx_blo7looa3eagp2kgn75n47fkrk
The rotation is the point. A UUIDv7 leads with a 48-bit millisecond
timestamp, so unrotated encodings of IDs minted together share a long
common prefix and the leading characters barely move for months.
Rotating left by 16 puts 10 characters of random bits in front and the
timestamp from index 10 — at the cost of encoded order no longer
following time, which the tests state outright so nobody indexes on it.
The alphabet is exactly the one base64.b32encode produces, so any
language can read these IDs with its standard library and no tables. The
interop suite drives python3 over the whole corpus to hold that claim to
account rather than trusting it.
No dependencies, and no runtime-specific API: a test asserts src reaches
for nothing but platform globals, so the package works in Workers, Deno,
Bun and browsers with no compat flags.
Not published yet. `changeset publish` releases any public workspace
package whose version is absent from the registry, so a public @e2b/id
would ship as a side effect of the next unrelated release — and creating
a new name in the @e2b scope needs rights the release token may not
have, which fails after the version-bump commit (the SDK-298 shape).
Marked private until that is arranged.
Co-Authored-By: Claude <noreply@anthropic.com>
ebc5708 to
27a952b
Compare


Stack: 1 of 2. This is the JavaScript half; #1628 adds the Python twin on top. Split for review — this PR is self-contained and its tests pass with
packages/python-idabsent.@e2b/idgives every service and SDK one spelling for a resource ID: a three-character kind prefix, an underscore, and the 26-character rotated base32 encoding of a UUID. No dependencies, and no runtime-specific API — a test assertssrcreaches for nothing but platform globals, so it works in Workers, Deno, Bun and browsers with no compat flags.The rotation is the point: a UUIDv7 leads with a 48-bit millisecond timestamp, so unrotated encodings of IDs minted together share a long common prefix and the leading characters barely move for months. Rotating left by 16 puts 10 characters of random bits in front and the timestamp from index 10 — at the cost of encoded order no longer following time, which the tests state outright so nobody indexes on it.
Part of SDK-303
Usage
Id<K>is a template literal type, so a mismatch is a compile error andisIdnarrows:Errors carry a
reason('kind' | 'prefix' | 'length' | 'alphabet' | 'canonical' | 'uuid') plusactualKind, so callers branch on a field rather than on message prose.projectworkspacevolumesandboxusergroupprjwrkvolsbxusrgrpNotes for reviewers
0,1,8or9— the alphabet is RFC 4648 base32 lowercased (a-z2-7), exactly whatbase64.b32encodeproduces. If you have seen prefixed-ID examples elsewhere with other digits, those were illustrative placeholders (confirmed); this implements the reference format verbatim and every golden vector reproduces exactly.0.1.0rejects a structurally valid ID for a kind added later. Known and accepted for now, to be handled before a seventh kind ships.changeset publishreleases any public workspace package whose version is absent from the registry, so a public@e2b/idwould ship as a side effect of the next unrelated release — and creating a new name in the@e2bscope needs rights the release token may not have, which fails after the version-bump commit (the SDK-298 shape). Markedprivateuntil that is arranged.Verification
108 tests, plus lint/typecheck/build clean. Beyond the suite: the built
distcontains zeronode:imports, and the interop suite drivespython3over the whole 1303-value corpus to hold the "any language can read these with its standard library" claim to account rather than trusting it.Golden vectors were computed with Python's
b32encoderather than captured from this implementation, so they check it rather than record it.CORPUS_DIGESTis the cross-implementation contract that #1628 pins from the other side.🤖 Generated with Claude Code